#include<iostream>
#include<string.h>

using std::cout;
using std::endl;
using std::cin;

class String
{
public:
    String(const char* pstr);
    ~String();
    class Charproxy
    {
    public:
    Charproxy(String& lhs,size_t idx)
        :_sso(lhs)
         ,_idx(idx)
        {}
    operator char();
    char operator=(char ch);
   friend std::ostream& operator<<(std::ostream& os,String::Charproxy& rhs);
    friend
        class String;
    private:
        String &_sso;
        size_t _idx;
    };
   Charproxy operator[](size_t idx);
   friend std::ostream& operator<<(std::ostream& os,String::Charproxy& rhs);

    friend
        std::ostream & operator<<(std::ostream & os,const String & rhs);
private:
    union Buffer{
        char* _pointer;
        char _local[16];
    };

    size_t _size;
    size_t _capacity;
    Buffer _buffer;
};
String::String(const char* pstr)
    :_size(strlen(pstr))
     ,_capacity(16)
{
    size_t length=strlen(pstr);
    cout<<length<<endl;
    if(length<16)
    {
        strcpy(_buffer._local,pstr);
    }
    else
    {
        _buffer._pointer=new char[strlen(pstr)+1]();
        _capacity=strlen(pstr);
        strcpy(_buffer._pointer,pstr);
    }
    cout<<"拷贝构造"<<endl;
}
String::Charproxy  String::operator[](size_t idx)
{
            return Charproxy(*this,idx);
}
String::Charproxy::operator char()
{
    cout<<"类型转换"<<endl;

    if(_sso._size<16)
    {
        return _sso._buffer._local[_idx];
    }
        return _sso._buffer._pointer[_idx];
}
String::~String()
{
    if(_size>15)
    {
        if(_buffer._pointer)
        {
            delete []_buffer._pointer;
            _buffer._pointer=nullptr;
        }
    }
}
    std::ostream& operator<<(std::ostream& os,String::Charproxy& rhs)
{

    if(rhs._idx<rhs._sso._size)
    {
        if(rhs._sso._size<16)
        {
           os<< rhs._sso._buffer._local[rhs._idx];
        }
        else 
        {
           os<< rhs._sso._buffer._pointer[rhs._idx];
        }
    }
    else
    {
        cout<<"out of range"<<endl;
    }
    return os;
}
    char String::Charproxy::operator=(char ch)
{
    if(_idx<_sso._size)
    {
        if(_sso._size<16)
        {
            _sso._buffer._local[_idx]=ch;
            return ch;
        }
        else 
        {
            _sso._buffer._pointer[_idx]=ch;
            return ch;
        }
    }
    static char sign = '\0';
    cout<<"out of range"<<endl;
    return sign;
}

  std::ostream & operator<<(std::ostream & os,const String & rhs)
{
    if(rhs._size>15)
    {
        cout<<rhs._buffer._pointer;
    }
    else 
    {
        cout<<rhs._buffer._local;
    }
    return os;
}


void test()
{

    String str1("hello");

    String str2("hello,world!!!!");
    cout<<str1<<str1[1]<<endl;
    cout<<str2<<str2[2]<<endl;
}

int main()
{
test();
}
